package br.edu.ufcg.lsd.wbis.control.user;

import br.edu.ufcg.lsd.wbis.control.util.matching.AbstractMatcher;
import br.edu.ufcg.lsd.wbis.control.util.matching.Matcher;
import br.edu.ufcg.lsd.wbis.control.util.matching.StringMatcher;

/**
 * Matches a user by comparing its fields. Supports matching of all user's
 * fields but its password. Allows string fields checking through default
 * equality, canse insensitive equality or regex pattern match.
 * 
 * @author Renato Miceli
 */
public class UserMatcher extends AbstractMatcher implements Matcher<User> {

	/**
	 * The matching name.
	 */
	private String name;

	/**
	 * The matching name checking type.
	 */
	private StringMatcher nameMatcher;

	/**
	 * The matching email.
	 */
	private String email;

	/**
	 * The matching email checking type.
	 */
	private StringMatcher emailMatcher;

	/**
	 * The matching login.
	 */
	private String login;

	/**
	 * The matching login checking type.
	 */
	private StringMatcher loginMatcher;

	/**
	 * The matching level.
	 */
	private UserLevel level;

	/**
	 * The matching authorization flag.
	 */
	private Boolean authorized;

	/**
	 * Builds a new User Matcher.
	 */
	public UserMatcher() {
		// Do nothing!
	}

	/**
	 * Sets this user matcher's name.
	 * 
	 * @param name
	 *            this user matcher's name
	 * @return this same user matcher
	 */
	public UserMatcher setName(String name) {
		this.name = name;
		return this;
	}

	/**
	 * Sets this user matcher's name checking type.
	 * 
	 * @param nameType
	 *            this user matcher's name checking type.
	 * @return this same user matcher
	 */
	public UserMatcher setNameSearchMatcher(StringMatcher nameMatcher) {
		this.nameMatcher = nameMatcher;
		return this;
	}

	/**
	 * Sets this user matcher's login.
	 * 
	 * @param login
	 *            this user matcher's login.
	 * @return this same user matcher
	 */
	public UserMatcher setLogin(String login) {
		this.login = login;
		return this;
	}

	/**
	 * Sets this user matcher's login checking type.
	 * 
	 * @param loginType
	 *            this user matcher's login checking type.
	 * @return this same user matcher
	 */
	public UserMatcher setLoginSearchMatcher(StringMatcher loginMatcher) {
		this.loginMatcher = loginMatcher;
		return this;
	}

	/**
	 * Sets this user matcher's email.
	 * 
	 * @param email
	 *            this user matcher's email.
	 * @return this same user matcher
	 */
	public UserMatcher setEmail(String email) {
		this.email = email;
		return this;
	}

	/**
	 * Sets this user matcher's email checking type.
	 * 
	 * @param emailType
	 *            this user matcher's email checking type.
	 * @return this same user matcher
	 */
	public UserMatcher setEmailSearchMatcher(StringMatcher emailMatcher) {
		this.emailMatcher = emailMatcher;
		return this;
	}

	/**
	 * Sets this user matcher's level.
	 * 
	 * @param level
	 *            this user matcher's level.
	 * @return this same user matcher
	 */
	public UserMatcher setUserLevel(UserLevel level) {
		this.level = level;
		return this;
	}

	/**
	 * Sets this user matcher's authorization flag.
	 * 
	 * @param authorized
	 *            this user matcher's authorization flag.
	 * @return this same user matcher
	 */
	public UserMatcher setAuthorized(Boolean authorized) {
		this.authorized = authorized;
		return this;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean matches(User user) {
		return matches(this.name, this.nameMatcher, user.getName()) && matches(this.email, this.emailMatcher, user.getEmail())
				&& matches(this.login, this.loginMatcher, user.getLogin()) && (matches(this.authorized, user.isAuthorized()))
				&& (!isMatcheable(this.level) || !isMatcheable(user.getLevel()) || this.level == user.getLevel());
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public String toString() {
		StringBuilder bld = new StringBuilder();
		bld.append("Login: ");
		bld.append(this.name);
		bld.append("\n");
		bld.append("Login Matcher: ");
		bld.append(this.loginMatcher);
		bld.append("\n");
		bld.append("Name: ");
		bld.append(this.name);
		bld.append("\n");
		bld.append("Name matcher: ");
		bld.append(this.nameMatcher);
		bld.append("\n");
		bld.append("Email: ");
		bld.append(this.email);
		bld.append("\n");
		bld.append("Email matcher: ");
		bld.append(this.emailMatcher);
		bld.append("\n");
		bld.append("Level: ");
		bld.append(this.level);
		bld.append("\n");
		bld.append("Authorized: ");
		bld.append(this.authorized);
		bld.append("\n");
		return bld.toString();
	}
}
